package com.cyneck.demo.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.cyneck.demo.constant.ColorEnumFactory;
import com.cyneck.demo.model.ApiResponseEntity;
import com.cyneck.demo.model.FaceRequestDto;
import com.cyneck.demo.model.ImageDto;
import com.cyneck.demo.service.MergeImageService;
import com.cyneck.demo.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Map;

/**
 * <p>Description:证件照 </p>
 * 1、点击指定尺寸的证件处理，上传图片
 * 2、后台保存原图；
 * 3、处理成小规格的图片交给第三方抠图
 * 4、保存抠图后的图片
 * 5、对口抠图后的照片换底和裁剪
 *
 * @author Eric Lee
 * @version v1.0.0
 * @since 2020/9/3 10:13
 **/

@Api(tags = "证件照")
@RestController
@RequestMapping(value = "/photo/*")
@Slf4j
public class IDPhotoController {

    @Autowired
    private Environment env;

    @Autowired
    private FaceImageClient faceImageClient;

    @Autowired
    private GaodingClientUtil gaodingClientUtil;

    @Value("${interface-supplier:gaoding}")
    private String interfaceSupplier;

    @Value("${serverDomain:idphoto.sakya.video}")
    private String serverDomain;


    /**
     * 用户图片目录,抠图后的图片路径
     */
    @Value("${path.user}")
    private String user_image_dir;

    /**
     * 原始图片路径
     */
    @Value("${path.origin}")
    private String pathOrigin;

    /**
     * url访问服务器路径,nginx配置化映射domainBaseUrl
     */
    @Value("${path.open}")
    private String pathOpen;

    /**
     * 图片baseUrl
     */
    @Value("${domain.baseUrl}")
    private String domainBaseUrl;

    /**
     * 临时图片tmpUrl
     */
    @Value("${domain.tmpFileDir:/tmp/}")
    private String tmpFileDir;

    /**
     * 临时url
     */

    private String tmpPrefixUrl;

    /**
     * 需要交给第三方处理的图片路径
     */
    private String fileBaseDomainUrl;

    @PostConstruct
    public void init() {
        tmpPrefixUrl = "https://" + serverDomain + tmpFileDir;
        fileBaseDomainUrl = "https://" + serverDomain + domainBaseUrl;
    }

    @Autowired
    private MergeImageService mergeImageService;

    @ApiOperation(value = "test")
    @PostMapping(value = "test")
    public ApiResponseEntity test(HttpServletRequest request, HttpServletResponse response) {

        return ApiResponseEntity.success();
    }


    @ApiOperation(value = "获取证件规格list")
    @GetMapping(value = "getIdPhotoTypeList")
    public ApiResponseEntity getIdPhotoTypeList() {
        log.info("获取证件规格list");
        File file = new File(System.getProperty("user.dir") + File.separator + "image" + File.separator + "photo_inch.json");
        JSONArray jsonObject = JSONUtil.readJSONArray(file, Charset.forName("utf-8"));
        return ApiResponseEntity.success(jsonObject);
    }


    @ApiOperation(value = "图片上传")
    @PostMapping(value = "uploadImage")
    public ApiResponseEntity<ImageDto> uploadImage(@RequestParam("imageFile") MultipartFile imageFile,
                                                   @RequestParam(value = "category", required = false) String category,
                                                   @RequestParam(value = "item", required = false) String item,
                                                   @RequestParam(value = "color", required = false, defaultValue = "white") String color,
                                                   @RequestParam(value = "sizeArray", required = false, defaultValue = "[295,413]") String sizeArray) throws Exception {

        log.info("证件上传.imageFile:{}，分类参数：{},item:{}，颜色{}，尺寸{}", imageFile.getOriginalFilename(), category, item, color, sizeArray);

        //修改文件名为唯一
        String uuid = UUID.fastUUID().toString();

        String filename = uuid + "." + FileUtil.extName(imageFile.getOriginalFilename());
        String originFileFullPath = pathOrigin + filename;
        String openUrlFullPath = pathOpen + filename;
        String imageDomainUrl = this.fileBaseDomainUrl + filename;

        //保存原图文件到目录下
        FileUtil.writeFromStream(imageFile.getInputStream(), originFileFullPath);

        if ("嘉年华".equals(category)) {
            FileUtil.copy(originFileFullPath, openUrlFullPath, true);
            return ApiResponseEntity.success(new ImageDto(filename, "", imageDomainUrl));
        } else {
            // 创建低分辨率图片，交给第三方抠图
            BufferedImage srcImage = ImageIO.read(imageFile.getInputStream());
            int[] resolution = {srcImage.getWidth(), srcImage.getHeight()};
            if (srcImage.getWidth() > ImageSizeConts.FIVE_INCH[0] || srcImage.getHeight() > ImageSizeConts.FIVE_INCH[1]) {
                resolution = new int[]{ImageSizeConts.FIVE_INCH[0], ImageSizeConts.FIVE_INCH[1]};
            }
            ImageHelper.compress(originFileFullPath, openUrlFullPath, resolution[0], resolution[1]);
        }

        //保存抠图后的照片的名称和全路径
        String dealedImageName = uuid + "_white.png";

        String dealedImagePath = user_image_dir + dealedImageName;

        String imageBase64Str = "";

        if (env.getActiveProfiles().length == 1 && env.getActiveProfiles()[0].equals("prod")) {
            // 调用人体抠图接口
            if ("gaoding".equals(interfaceSupplier)) {
                log.info("搞定抠图接口调用开始");
                HttpEntity httpEntity = gaodingClientUtil.cutoutPhoto(imageDomainUrl);
                String jsonObj = EntityUtils.toString(httpEntity);
                Map data = JSONObject.parseObject(jsonObj);
                String imageUrl = data.get("result").toString();
                if (StringUtils.isBlank(imageUrl)) {
                    log.error("搞定抠图接口返回错误：{}", data.get("message").toString());
                    return ApiResponseEntity.fail(HttpStatus.BAD_REQUEST, data.get("message").toString());
                }
                //保存到应用目录下
                gaodingClientUtil.downLoadFromUrl(imageUrl, dealedImageName, user_image_dir);
                imageBase64Str = ImageUtils.getImageBase64Str(dealedImagePath);
            } else if ("face++".equals(interfaceSupplier)) {
                log.info("旷视接口调用开始");
                byte[] imageBytes = ImageHelper.getBytesFromStream(new FileInputStream(new File(openUrlFullPath)));
                Map result = faceImageClient.getSegmentImageByForm("0", imageBytes);
                imageBase64Str = (String) result.get("body_image");

                //保存到应用目录下
                ImageUtils.generateImage(imageBase64Str, dealedImagePath);
                if (null == result || null != result.get("error_message")) {
                    log.error("旷视接口返回错误：{}", result.get("error_message").toString());
                    return ApiResponseEntity.fail(HttpStatus.BAD_REQUEST, result.get("error_message").toString());
                }

            } else {
                return ApiResponseEntity.fail("暂无接口供应商提供服务");
            }

            log.info("接口调用完成");
        } else {
            //已经抠图好的图片
            String tmpFilePath = System.getProperty("user.dir") + File.separator + "image" + File.separator + "face-p.png";
            File fileDev = new File(tmpFilePath);
            if (!fileDev.exists()) {
                return ApiResponseEntity.fail(HttpStatus.BAD_REQUEST, "测试图片不存在");
            }
            Map result = faceImageClient.getSegmentImageDev(tmpFilePath);
            imageBase64Str = (String) result.get("body_image");

            //保存到应用路径目录一下
            String saveImageFullPath = user_image_dir + dealedImageName;
            ImageUtils.generateImage(imageBase64Str, saveImageFullPath);
        }
        return ApiResponseEntity.success(new ImageDto(dealedImageName, imageBase64Str, ""));
    }


    @ApiOperation(value = "证件换底尺寸修改接口")
    @RequestMapping(value = "changeSize", method = {RequestMethod.GET, RequestMethod.POST})
    public ApiResponseEntity<ImageDto> changeSize(@RequestParam(value = "category", required = false) String category,
                                                  @RequestParam(value = "item", required = false) String item,
                                                  @RequestParam("imageName") String imageName,
                                                  @RequestParam(value = "color", required = false, defaultValue = "white") String color,
                                                  @RequestParam(value = "sizeArray", required = false, defaultValue = "[295,413]") String sizeArray) throws Exception {

        log.info("证件尺寸修改接口,请求参数：imageName：{},color:{},sizeArray:{}，category：{},item:{}", imageName, color, sizeArray, category, item);
        int[] size;
        String[] strArray = sizeArray.replaceAll("\\[|\\]", "").split(",");
        if (strArray.length == 2) {
            size = new int[]{Integer.parseInt(strArray[0]), Integer.parseInt(strArray[1])};
        } else {
            return ApiResponseEntity.fail("sizeArray参数格式错误");
        }

        String imageDomainUrl = "https://" + serverDomain + domainBaseUrl + imageName;
        String targetFilePath = user_image_dir + imageName;
        if (!FileUtil.exist(targetFilePath)) {
            return ApiResponseEntity.fail("图片不存在");
        }

        String imageBase64Str = "";
        if ("嘉年华".equals(category) || "进入活动图片合成".equals(item)) {
            //活动照片合成，原图
            String dealedImageFilePath = RemoteImageClient.dealImage(targetFilePath);//人脸检测处理
            File file = mergeImageService.TemplateMergeImage(new File(targetFilePath));
//            imageBase64Str = mergeImageService.changeColor(file, color);
            return ApiResponseEntity.success(new ImageDto(imageName, "", imageDomainUrl));
        }

        BufferedImage image = ImageIO.read(new File(user_image_dir + imageName));
        int w = image.getWidth();
        int h = image.getHeight();

        //创建一个width xheight ，RGB高彩图，类型可自定
        BufferedImage background = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        //取得图形
        Graphics graphics = background.getGraphics();
        //设置颜色
        graphics.setColor(ColorEnumFactory.create(color));
        //填充
        graphics.fillRect(0, 0, w, h);
        //加工合成图
        BufferedImage bufferedImage = MergeImageUtil.mergePendant(background, image, 0, 0, 1.0f);
        InputStream inputStream = ImageUtils.bufferedImageToInputStream(bufferedImage);
        imageBase64Str = ImageUtils.getImageBase64Str(inputStream);

        InputStream imageInputStream = ImageUtils.convertStream(imageBase64Str);


        //缩放裁剪图片,保存裁剪后的照片,裁剪后的照片
        String tmpDealFile = tmpFileDir + FileUtil.mainName(imageName) + ".jpg";
        ImageHelper.compress(imageInputStream, tmpDealFile, size[0], size[1]);
        imageBase64Str = ImageUtils.getImageBase64Str(new FileInputStream(tmpDealFile));
        return ApiResponseEntity.success(new ImageDto(imageName, imageBase64Str, tmpPrefixUrl + FileUtil.mainName(imageName) + ".jpg"));

    }


    @ApiOperation(value = "证件人像优化")
    @RequestMapping(value = "changeFace", method = {RequestMethod.POST})
    public ApiResponseEntity<ImageDto> changeFace(@RequestBody FaceRequestDto faceRequestDto) throws FileNotFoundException {
        log.info("人像优化：{}", faceRequestDto);
        String tmpFileName = FileUtil.mainName(faceRequestDto.getImageName()) + "_makeup.jpg";
        String tmpUrl = tmpPrefixUrl + tmpFileName;

        String targetFilePath = tmpFileDir + FileUtil.mainName(faceRequestDto.getImageName()) + ".jpg";
        byte[] imageBytes = ImageHelper.getBytesFromStream(new FileInputStream(new File(targetFilePath)));

        if (faceRequestDto.getEnlarge_eye() == 0
                && faceRequestDto.getShrink_face() == 0
                && faceRequestDto.getSmoothing() == 0
                && faceRequestDto.getThinface() == 0
                && faceRequestDto.getWhitening() == 0) {
            FileUtil.copy(targetFilePath, tmpFileDir + tmpFileName, true);
            return ApiResponseEntity.success(new ImageDto(faceRequestDto.getImageName(), "", tmpUrl));
        } else {
            Map result = faceImageClient.getFace(imageBytes, faceRequestDto);
            String imageBase64Str = (String) result.get("result");
            //保存到临时目录下
            ImageUtils.generateImage(imageBase64Str, tmpFileDir + tmpFileName);
            if (null == result || null != result.get("error_message")) {
                log.error("旷视接口返回错误：{}", result.get("error_message").toString());
                return ApiResponseEntity.fail(HttpStatus.BAD_REQUEST, result.get("error_message").toString());
            }
            return ApiResponseEntity.success(new ImageDto(faceRequestDto.getImageName(), "", tmpUrl));
        }

    }


    @ApiOperation(value = "下载图片")
    @RequestMapping(value = "downloadImage", method = {RequestMethod.GET})
    public ApiResponseEntity<ImageDto> downloadImage(@RequestParam("tag") String tag,
                                                     @RequestParam("makeup") String makeup,
                                                     @RequestParam("imageName") String imageName) throws Exception {
        log.info("下载图片：tag：{}，makeup：{}，imageName：{}", tag, makeup, imageName);
        String tmpFilePath = FileUtil.mainName(imageName) + ".jpg";

        String resultImage = tmpFileDir + tmpFilePath;

        String tmpUrl = tmpPrefixUrl + tmpFilePath;

        if ("1".equals(makeup)) {
            //美颜过
            tmpFilePath = FileUtil.mainName(imageName) + "_makeup.jpg";
            resultImage = tmpFileDir + tmpFilePath;
            tmpUrl = tmpPrefixUrl + tmpFilePath;
        }

        if ("1".equals(tag)) {
            //整版
            String fullPageImage = tmpFileDir + FileUtil.mainName(imageName) + "_page.jpg";
            String base64Image = mergeImageService.splicingImage(new File(resultImage));
            ImageUtils.generateImage(base64Image, fullPageImage);
            tmpUrl = tmpPrefixUrl + FileUtil.mainName(imageName) + "_page.jpg";
            return ApiResponseEntity.success(new ImageDto(imageName, "", tmpUrl));
        } else {
            //单张
            return ApiResponseEntity.success(new ImageDto(imageName, "", tmpUrl));
        }

    }
}
